#light

module Dwarf_Managed_Common

open System
open System.IO
open System.Text
open System.Collections.Generic
open System.Runtime.InteropServices
open System.Globalization
open Microsoft.FSharp.Core
open Microsoft.FSharp.NativeInterop

type TyRef = Microsoft.FSharp.Core.nativeptr<double>


/// <summary>
/// Start the time count.
/// </summary>
[<DllImport(@"CliTools.dll")>]
extern void start()

/// <summary>
/// Stop the time count.
/// </summary>
/// <param name="time">
/// Value of the time.
/// </param>
[<DllImport(@"CliTools.dll")>]
extern void stop(TyRef time)

/// <summary>
/// Default size for buffer.
/// </summary>
let BUFFER_SIZE = 1024;

/// <summary>
/// Constructor that init strings.
/// </summary>
let mutable inputFile = ""
let mutable profileFile = ""
let mutable resultFile = ""

let mutable msize = 0

/// <summary>
/// Left matrix.
/// </summary>
let mutable lgrid = Array2D.zeroCreate<double> 0 0

/// <summary>
/// Right matrix.
/// </summary>
let mutable rgrid = Array2D.zeroCreate<double> 0 0

/// <summary>
/// Result matrix.
/// </summary>
let mutable result = Array2D.zeroCreate<double> 0 0
    

/// <summary>
/// Problem results output.
/// </summary>
/// <param name="dlasolver">
/// Instance of Solver.
/// </param>
let Finish () =
    let mutable time = 0.0
    stop(&&time)

    Console.WriteLine()
    Console.WriteLine("Clock time (sec): {0} ", time.ToString("F8"))

    try        
        use outputResult = System.IO.File.CreateText resultFile
        use outputProfile = System.IO.File.CreateText profileFile
        
        outputProfile.WriteLine("#Dwarfname:{0}", Constants.DWARF_NAME)

        outputProfile.WriteLine("#Time: {0}", DateTime.Now.ToString())

        outputProfile.WriteLine("#Dimensions: 2")
        outputProfile.WriteLine("#Matrix Size: {0}", msize)
        outputProfile.WriteLine("#Result time (sec): {0}", time.ToString("F8"))
        outputResult.WriteLine("#Result domain:")
        
        for i = 0 to msize - 1 do
            for j = 0 to msize - 1 do
                outputResult.Write("{0} ", result.[i, j].ToString("F8", CultureInfo.InvariantCulture))
            outputResult.WriteLine()        
        outputProfile.WriteLine("#eof")
 
    with e -> Console.WriteLine(e.Message); reraise()
        
/// <summary>
/// Start the time count.
/// </summary>
let Start() =
    start()

/// <summary>
/// Get one line from stream.
/// </summary>
/// <param name="dlasolver">
/// Stream to get from.
/// </param>
let rec GetLine(sr : StreamReader) =
    let s = sr.ReadLine()
    //Avoid comments lines.
    match s with
    | null -> s
    | _ -> if s.StartsWith("#") || s.StartsWith("//") then GetLine sr else s

/// <summary>
/// Parse input file into solver's structures.
/// </summary>
/// <param name="dlasolver">
/// Instance of Solver.
/// </param>
let parseConfigFile() =
    // Open the file to read from.
    try        
        use sr = File.OpenText inputFile
        //Get size of matrices.
        //let msize = Int32.Parse(GetLine(sr))
        msize <- Int32.Parse(GetLine(sr))

        lgrid <- Array2D.zeroCreate<double> msize msize
        rgrid <- Array2D.zeroCreate<double> msize msize
        result <- Array2D.zeroCreate<double> msize msize

        //Get left matrix.
        for i = 0 to msize - 1 do
            let str = GetLine(sr).Split(' ');
            
            for j = 0 to msize - 1 do
                lgrid.[i, j] <- Double.Parse(str.[j]);        
           
        
        //Get right matrix.
        for i = 0 to msize - 1 do
            let str = GetLine(sr).Split(' ');
            
            for j = 0 to msize - 1 do
                rgrid.[i, j] <- Double.Parse(str.[j]);
                        
    with e -> Console.WriteLine(e.Message); reraise()
        

/// <summary>
/// Write settings.
/// </summary>
/// <param name="dlasolver">
/// Instance of Solver.
/// </param>
let WriteSettings() =
    // Write general settings.
    Console.WriteLine("Kernel settings summary : ")
    Console.WriteLine("Dwarf name              : {0} ", Constants.DWARF_NAME)
    Console.WriteLine("Matrix size             : {0} ", msize)
    Console.WriteLine("Inputfile               : {0} ", inputFile)
    Console.WriteLine("Profilefile             : {0} ", profileFile)
    Console.WriteLine("Resultfile              : {0} ", resultFile)
    Console.WriteLine()

/// <summary>
/// Init variables, parse cli params and input file.
/// </summary>
/// <param name="args">
/// Cli params.
/// </param>
/// <param name="dlasolver">
/// Instance of Solver.
/// </param>
let Init(args : String[]) =
    
    for i = 0 to args.Length - 1 do
        let str = args.[i]
        
        if str.StartsWith("/inputfile:") then
            inputFile <- str.Substring(11)
            
        if str.StartsWith("/resultfile:") then
            resultFile <- str.Substring(12)
        
        if str.StartsWith("/profilefile:") then
            profileFile <- str.Substring(13)
            
    //Parse input file.
    parseConfigFile()

    // write settings if it's needed
    WriteSettings()
